/*
 * Comm_Manager.cpp
 *
 *  Created on: Mar 7, 2012
 *      Author: ajeffery
 */

#include "Comm_Manager.h"
#include "defs.h"
#include "Elevator.h"

#include <native/task.h>
#include <native/timer.h>
#include <rtdk.h>

#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

extern Elevator *this_lift;

Comm_Manager::Comm_Manager(Double_Buffer *iBuffer) {

	struct sockaddr_in serv_addr;
	buffer = iBuffer;

	ecSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (ecSocket < 0) {
			perror("ERROR opening ecSocket");
			exit(-1);
	}

	int flag =1;
	int result =setsockopt(ecSocket, IPPROTO_TCP, TCP_NODELAY,
			(char*) &flag, sizeof(int));
	if (result < 0)
		perror("Failed to remove delay from ecSocket");

	serv_addr.sin_family = AF_INET;
	inet_aton(SERVER_ADDR, &serv_addr.sin_addr);
	serv_addr.sin_port = htons(SERVER_PORT);
	while(connect(ecSocket,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
		rt_task_sleep(SLEEP1S);

	rt_printf("Group Dispatcher Found \n");

}

void Comm_Manager::readSocket(){
	char buff[BUF_SIZE];
	memset(buff, 0, BUF_SIZE);

	while(ecSocket > 0){
		int retval = read(ecSocket, buff, BUF_SIZE);
		if (retval < 0)
				perror("ERROR:: ecSocket read Fail");
		else
			parse(buff, BUF_SIZE);
	}
}

void Comm_Manager::parse(char* iMsg, int len){
	int8_t type;
	type = (int8_t) iMsg[0];
	char reply_buf[BUF_SIZE];
	memset(reply_buf, 0 , BUF_SIZE);
	switch(type){
		case (STATUS_REQUEST):{
			rt_printf("Received STAT_REQ \n");
			srep_t stat_rep;
			//status_t cur_status;
			//cur_status = buffer->get(COMM_MANAGER_BUFFER_ID);

			//Send out reply first to status request
			stat_rep.type = STATUS_REPLY;
			stat_rep.car=this_lift->getCar_num();
			stat_rep.cur_floor= this_lift->getCur_floor();



			stat_rep.dest_floor= this_lift->getDest_floor();
			if (stat_rep.dest_floor != stat_rep.cur_floor || SPOOLING )
				stat_rep.direction=this_lift->getDirection();
			else
				stat_rep.direction=UP;

			//rt_printf("Direction is %d", stat_rep.direction);

			stat_rep.status=this_lift->getStatus();
			this_lift->getCur_hall_calls(stat_rep.cur_hall_calls);




			char* current = reply_buf;

			//rt_printf("Current status is %d \n", stat_rep.status);

			memcpy(current, (char*) &(stat_rep.type), sizeof(stat_rep.type));
			current +=sizeof(stat_rep.type);
			memcpy(current, (char*) &(stat_rep.car), sizeof(stat_rep.car));
			current +=sizeof(stat_rep.car);
			memcpy(current, (char*) &(stat_rep.cur_floor), sizeof(stat_rep.cur_floor));
			current +=sizeof(stat_rep.cur_floor);
			memcpy(current, (char*) &(stat_rep.dest_floor), sizeof(stat_rep.dest_floor));
			current +=sizeof(stat_rep.dest_floor);
			memcpy(current, (char*) &(stat_rep.status), sizeof(stat_rep.status));
			current +=sizeof(stat_rep.status);
			memcpy(current, (char*) &(stat_rep.direction), sizeof(stat_rep.direction));
			current +=sizeof(stat_rep.direction);
			memcpy(current, (char*) &(stat_rep.cur_hall_calls[0]), sizeof(stat_rep.cur_hall_calls[0])*MAX_FLOORS);

			int err =write(ecSocket, reply_buf, BUF_SIZE);
			if (err < 0)
				perror("ERROR:: ecSocket Write Failed");

			//Handle new info in received msg
			sreq_t *iRequest;
			iRequest = (sreq_t*) iMsg;
			this_lift->add_hall_calls(iRequest->new_hall_calls);
			this_lift->cancel_hall_calls(iRequest->cancel_hall_calls);
			break;
		}
		case (FLOOR_REQUEST):
			break;
		default:
			break;
	 }
}

Comm_Manager::~Comm_Manager() {
	if (ecSocket)
		close(ecSocket);
}
